﻿using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.EventSystems;
using Random = UnityEngine.Random;

public enum ResultJudgeType
{
    SaveWidgets = 0,
    KillEnemy = 1,
}

public interface IMBattleController : IBattleControllerView
{
    void HidePlayerInfo(RoleEntity role);
    void OnTimeOut();
    void OnTriggerBoss();
    void AddValueToast(int value);
}


/// <summary>
/// battle core data controller
/// </summary>
public partial class MBattleController : BattleController
{
    /// <summary>
    /// battle data config
    /// </summary>
    private MBattleDataConfig _mMBattleDataConfig;
    public MBattleDataConfig MBattleDataConfig => _mMBattleDataConfig;

    #region Layers
    public static LayerMask layerBulletMask => LayerMask.GetMask("Bullet");
    public static int layerBullet => LayerMask.NameToLayer("Bullet");
    public static int layerInetract => LayerMask.NameToLayer("Inetract");
    public static LayerMask layerInetractMask => LayerMask.GetMask("Inetract");
    public static LayerMask layerBossMask => LayerMask.GetMask("Boss");
    public static int layerBoss => LayerMask.NameToLayer("Boss");

    private const string Layer_Widget_Name = "Widget";
    public static int layerWidget => LayerMask.NameToLayer(Layer_Widget_Name);
    public static LayerMask LayerWidgetMask => LayerMask.GetMask(Layer_Widget_Name);

    private const string Layer_Block_Name = "Block";
    public static int layerBlock => LayerMask.NameToLayer(Layer_Block_Name);
    public static LayerMask layerBlockMask => LayerMask.GetMask(Layer_Block_Name);

    private const string Layer_Ground_Name = "Ground";
    public static int layerGround => LayerMask.NameToLayer(Layer_Ground_Name);
    public static LayerMask layerGroundMask => LayerMask.GetMask(Layer_Ground_Name);

    private const string Layer_Player_Name = "Player";
    public static int layerPlayer => LayerMask.NameToLayer(Layer_Player_Name);
    public static LayerMask layerPlayerMask => LayerMask.GetMask(Layer_Player_Name);
    private const string Layer_Enemy_Name = "Enemy";
    public static int layerEnemy => LayerMask.NameToLayer(Layer_Enemy_Name);
    public static LayerMask layerEnemyMask => LayerMask.GetMask(Layer_Enemy_Name);
    #endregion

    /// <summary>
    /// remaining time
    /// </summary>
    public int timeLeft => Mathf.Max(Mathf.CeilToInt(this.limitTime - this.time), 0);

    /// <summary>
    /// interface of battle data
    /// </summary>
    private IMBattleController m_GameBattleListener;
    public IMBattleController IGameBattleController => m_GameBattleListener;

    /// <summary>
    /// whether is first time to play game
    /// </summary>
    bool m_FirstTimeLevel;

    public override IBattleControllerView battleListener
    {
        get => m_GameBattleListener;
        set
        {
            m_GameBattleListener = value as IMBattleController;
        }
    }

    /// <summary>
    /// battle result judgement
    /// </summary>
    BattleResultChecker m_BattleResultChecker;

    private SwordsmanCamera m_BattleCam;
    public SwordsmanCamera battleCam
    {
        get
        {
            if (m_BattleCam == null)
                m_BattleCam = GetComponentInChildren<SwordsmanCamera>();
            return m_BattleCam;
        }
    }

    private Player m_Me;
    public Player me => m_Me;

    private AssemblerPropertyShow m_PropertyShow;
    public AssemblerPropertyShow propertyShow => m_PropertyShow;
    
    public bool win { get; set; }
    public bool fail { get; set; }

    public int skinId => this.me.roleId;

    public bool homeScene = true;
    
    ZTransformAnim zTransformAnim;
    public ZTransformAnim TransformAnim
    {
        get
        {
            if (zTransformAnim == null) zTransformAnim = this.gameObject.AddComponent<ZTransformAnim>();
            return zTransformAnim;
        }
    }
    protected override void Awake()
    {
        base.Awake();

        m_Me = logicItemsParent.GetComponentInChildren<Player>();
        m_BattleResultChecker = GetComponent<AchievedBattleResultChecker>();
        
        if (homeScene)
        {
            m_PropertyShow = logicItemsParent.GetComponentInChildren<AssemblerPropertyShow>();
        }

    }

    public void InitBattle(GameBattleData battleData, int myPlayerId, MBattleDataConfig dataConfig)
    {
        GameDebug.Log($"Init:{battleData} ");
        base.Init(battleData, myPlayerId,  dataConfig);

        m_FirstTimeLevel = battleData.firstTimeLevelGame;

        this._mMBattleDataConfig = dataConfig;
        if(me)
            me.Init(battleData.players.Find(e=>e.playerId == myPlayerId),dataConfig);

        if (homeScene)
        {
            if (m_PropertyShow)
            {
                m_PropertyShow.Init(me);
            }
        }

        /*LevelArche level = dataConfig.GetLevel(battleData.level);
        if (level != null)
        {
            this.m_LimitTime = level.limitTime;
        }*/
        InitResultChecker();
    }


    void InitResultChecker()
    {
        if(!m_BattleResultChecker)
            m_BattleResultChecker = gameObject.AddComponent<AchievedBattleResultChecker>();

        m_BattleResultChecker.Init(this);
    }


    public override void GameStart()
    {
        base.GameStart();

        this.m_GameBattleListener?.OnBattleStart();

        if (!homeScene)
        {
            me.MoveForward();
        }
    }

    public enum SceneType
    {
        heightWeightScene,
        MoneyScene,
        EduScene,
    }

    public SceneType sceneType = SceneType.heightWeightScene;
    protected override void BattleFinish()
    {
        var battleResult = GetBattleResult();

        this.m_GameBattleListener?.OnBattleEnd(battleResult);

        Time.timeScale = 1;

        if (battleResult.win)
        {
            if (sceneType == SceneType.heightWeightScene)
            {
                float addRate = 0.5f;
                
                MGame.instance.MUser.UpdateHeight(Mathf.Lerp(MGame.instance.MUser.userInfo.height,me.height,addRate));
                MGame.instance.MUser.UpdateWeight(Mathf.Lerp(MGame.instance.MUser.userInfo.weight,me.weight,addRate));
            }
            else if (sceneType == SceneType.MoneyScene)
            {
                MGame.instance.MUser.UpdateIncome(me.income);
            }  
            else if (sceneType == SceneType.EduScene)
            {
                if (me.eduScore >= 60)
                {
                    MGame.instance.MUser.UpdateEducation(MGame.instance.MUser.userInfo.eduation + 1);
                }
            }
        }
        
        GameDebug.Log($"game end：{this.level}  userScore:{battleResult.score}");
    }

    protected override void Update()
    {
        base.Update();

        if (m_State != State_Gaming && m_State != State_NotStarted)
            return;


        if (Input.GetKey(KeyCode.S))
        {
            ScreenshotHelper.Capture();
        }
    }

    private static float hapticMinInterval = 0.1f;
    private static float s_LastHapticTime;
    public static void Haptic()
    {
        if(Time.time - s_LastHapticTime > hapticMinInterval)
        {
            s_LastHapticTime = Time.time;
             
            MoreMountains.NiceVibrations.MMVibrationManager.Haptic(MoreMountains.NiceVibrations.HapticTypes.HeavyImpact);
        }
    }
    
    public void OnUpdateRole(int skinId)
    {
        me.ShowSkin(skinId);
    }
    
    public void ShowSkinCam()
    {
        this.battleCam.ShowSkinCam();
    }

    public void ShowNormalCam()
    {
        this.battleCam.ShowNormalCam();
    }
}
